﻿using System;
using System.Collections.Generic;
using System.Linq;
using Interface;
using Model;
namespace Controller
{
    public class MyController // Controller is written by Tien, Trang, Rud, Per & Enemark
    {
        #region Fields
        private readonly DBFacade dbFacade;
        private Operator _operator;
        public OperatorCollection operatorCollection;
        private OperatorSession _operatorSession;
        public OperatorSessionCollection OperatorSessionCollection;
        public IRid tempRid;
        public RidCollection ridCollection;
        public FbmReportCollection fbmReportCollection;
        public FbmFeatureCollection fbmFeatureCollection;
        public FbmDataCollection fbmDataCollection;
        public NoteCollection noteCollection;
        #endregion

        #region Properties
        public bool IsConnected { get; set; }
        public IOperator CurrentOperator { get; set; }
        public IEnumerable<IFeatureMask> FMask { get; set; }
        public IFeatureMask CurrentFeatureMask { get; set; }
        public string Emne { get; set; }
        public string PLNR { get; set; }
        #endregion

        /// <summary>
        /// Remember to assign database, name and password.
        /// </summary>
        /// <param name="dataSource"></param>
        /// <param name="username"></param>
        /// <param name="password"></param>
        public MyController(string dataSource, string username, string password)
        {
            dbFacade = new DBFacade(this, dataSource, username, password); // Instantier
            IsConnected = dbFacade.IsConnected; //is needed for verification
            if (IsConnected) //If connection to database
            {
                operatorCollection = new OperatorCollection();
                OperatorSessionCollection = new OperatorSessionCollection();
                ridCollection = new RidCollection();
                fbmReportCollection = new FbmReportCollection();
                fbmFeatureCollection = new FbmFeatureCollection();
                fbmDataCollection = new FbmDataCollection();
                noteCollection = new NoteCollection();
                dbFacade.LoadAllData(); // Indlæs data
                CurrentOperator = null; //Set session operatør
            }
        }

        /// <summary>
        /// This method checks if there is new data in the database and refreshes if there is
        /// </summary>
        /// <returns>True if there is new data in the db</returns>
        public bool Refresh()
        {
            var latestFromDb = dbFacade.GetLastRid();
            var latestFromList = ridCollection.RidCol.Max(x => x.RId);
            Console.WriteLine("Latest from DB: {0}\nLatest from list: {1}", latestFromDb, latestFromList);
            if (latestFromDb != latestFromList) // If the variables aren't equal, it's because we have new data waiting:
            {
                dbFacade.LoadLatest(latestFromList);
                return true;
            }
            return false;
        }

        public void RefreshOperatorSession()
        {
            OperatorSessionCollection = null;
            OperatorSessionCollection = new OperatorSessionCollection();
            dbFacade.LoadOperatorSession();
        }

        #region Add to model
        public void AddRid(long rid, string entity, DateTime createDate, DateTime updateDate, bool deleted, bool hidden,
                           bool disabled, string synUUid) // Add Rid
        {
            ridCollection.Add(rid, entity, createDate, updateDate, deleted, hidden, disabled, synUUid);
        }
        public void AddReport(int id, long rid, string serial, string model, string mident, string mPart,
                              string reportFileName) // Add report
        {
            fbmReportCollection.Add(id, ridCollection.FindRid(rid), serial, model, mident, mPart, reportFileName);
        }
        public void AddFeature(int id, string ident, string name, string ctrl, double nominal, double tolpos,
                               double tolneg) // Add feature
        {
            fbmFeatureCollection.Add(id, fbmReportCollection.Find(ident), name, ctrl, nominal, tolpos, tolneg);
        }
        public void AddData(int id, int fbmrid, int fbmfid, double measured, double deviation, bool test) // Add Data
        {
            fbmDataCollection.Add(id, fbmReportCollection.Find(fbmrid), fbmFeatureCollection.Find(fbmfid), measured, deviation, test);
        }
        public void AddOperator(string initials, string password, bool isEnabled) // Add Operator
        {
            _operator = operatorCollection.Add(initials, password, isEnabled);
        }
        public void AddOperatorSession(string initials, DateTime startTime, DateTime endTime) // Add operator session
        {
            _operatorSession = OperatorSessionCollection.Add(initials, startTime, endTime);
        }
        public void AddNote(int did, double newValue, double oldValue, string ndescription, DateTime nUpdateDate,
                            IOperator currentOperater) // Add note
        {
            noteCollection.Add(fbmDataCollection.Find(did), newValue, oldValue, ndescription, nUpdateDate, currentOperater);
        }
        #endregion

        #region Add to DB
        public void AddOperator2Db(string initials, string password, bool isEnabled) // Add operator to db and list
        {
            dbFacade.AddOperator(initials, password, isEnabled); // add to db
            AddOperator(initials, password, isEnabled); // add to list
        }
        public void AddOperatorSession2DB(string initials, DateTime startTime, DateTime endTime) // Add operator session to db and list
        {
            dbFacade.AddOperatorSession(initials, startTime, endTime); // add to db
            AddOperatorSession(initials, startTime, endTime); // add to list
        }
        public void AddNote2DB(int did, double newValue, double oldValue, string nDescription, DateTime nUpdateDate, string initials) //Add feature note to db
        {
            dbFacade.AddNote(did, newValue, oldValue, nDescription, nUpdateDate, CurrentOperator.Initials);
        }
        #endregion

        #region Update
        public void UpdateData(int did, double newvalue, double deviation, bool test) //Update data - Trang
        {
            dbFacade.UpdateData(did, newvalue, deviation, test); //update measured in database
            //update measured in object
            var data = (from d in fbmDataCollection.DataCol
                        where d.Id == did
                        select d).SingleOrDefault();
            if (data != null)
            {
                data.Measured = newvalue;
                data.Deviation = deviation;
                data.Test = test;
            }
        }
        public void UpdateOperator(string initials, string pass, bool isEnabled) // Update operator
        {
            string password = pass;
            _operator = (Operator)operatorCollection.Find(initials);
            if (pass.Length == 0) //Don't change pass in db if not set in gui
                password = _operator.Password;
            dbFacade.UpdateOperator(initials, password, isEnabled);
            operatorCollection.Edit(_operator, password, isEnabled);
        }
        public void UpdateOperatorSession(DateTime endTime) // Update operator session
        {
            dbFacade.UpdateOperatorSession(_operatorSession.Initials, _operatorSession.StartTime, endTime);
            OperatorSessionCollection.Edit(_operatorSession.Initials, _operatorSession.StartTime, endTime);
        }
        public void UpdateNote(int did, double newValue, string nDescription, DateTime nUpdateDate, string initials)// Update note
        {
            dbFacade.UpdateNote(did, newValue, nDescription, nUpdateDate, initials);
            var note = (from n in noteCollection.NoteCol.Cast<INote>().ToList()
                        where n.Did.Id == did
                        select n).SingleOrDefault();
            if (note != null)
            {
                note.NewValue = newValue;
                note.NDescription = nDescription;
                note.NUpdateDate = nUpdateDate;
            }
        }
        #endregion

        #region Find
        public bool FindNote(int did) //if did is existed, so overwrite.
        {
            return noteCollection.NoteCol.Any(note => note.Did.Id == did);
        }
        //public IOperatorSession FindOperatorSession(string initials) //Find operatorsession
        public IOperatorSession FindOperatorSession(string initials) //Find operatorsession
        {
            IOperatorSession _ios = null;
            if (OperatorSessionCollection != null)
            {
                foreach (IOperatorSession ios in OperatorSessionCollection.GetOperatorSessionList().Cast<IOperatorSession>().Where(ios => ios.Initials == initials))
                {
                    if (_ios != null && _ios.StartTime < ios.StartTime)
                        _ios = ios;
                    _ios = ios;
                }
            }
            return _ios;
        }
        #endregion

        #region Get lists
        public List<IFbmReport> GetReport() // Get reports
        {
            return fbmReportCollection.ReportCol.Cast<IFbmReport>().ToList();
        }
        public List<IFbmFeature> GetFeature() // Get features 
        {
            return fbmFeatureCollection.FeatureCol.Cast<IFbmFeature>().ToList();
        }
        public List<IFbmData> GetData() // Get data
        {
            return fbmDataCollection.DataCol.Cast<IFbmData>().ToList();
        }
        public List<IOperator> GetOperator()// Get operators
        {
            return operatorCollection.OperatorCol.Cast<IOperator>().ToList();
        }
        public List<INote> GetNote() //Get note
        {
            return noteCollection.NoteCol.Cast<INote>().ToList();
        }
        public List<IFeatureMask> DgData(string segment, string plnr)// Get the data, that is to be shown in the datagrid
        {
            var features =
                (from d in fbmDataCollection.DataCol
                 join n in noteCollection.NoteCol
                     on d.Id equals n.Did.Id into dN
                 where d.FbmRId.Model == segment && d.FbmRId.Serial == plnr
                 from n in dN.DefaultIfEmpty()
                 select new FeatureMask
                 {
                     Model = d.FbmRId.Model,
                     Serial = d.FbmRId.Serial,
                     Fid = d.FbmFId.Id,
                     Did = d.Id,
                     Name = d.FbmFId.Name,
                     Nominal = d.FbmFId.Nominal,
                     TolPos = d.FbmFId.TolPos,
                     TolNeg = d.FbmFId.TolNeg,
                     Measured = d.Measured,
                     Deviation = d.Deviation,
                     Test = d.Test ? "Pass" : "Fail",
                     NDescription = n == null ? string.Empty : n.NDescription + " Updateret ved " + n.NUpdateDate + " af " + n.Initilas.Initials
                 }).ToList<IFeatureMask>();
            return features;
        }
        public List<IFeatureMask> FoundItems(string searchText) // Get items that is found when actor has performed a search
        {
            string sText = searchText.ToLower();

            var features =
                (from d in fbmDataCollection.DataCol
                 join n in noteCollection.NoteCol
                     on d.Id equals n.Did.Id into dN
                 where d.FbmFId.Name.ToLower().Contains(sText) ||
                 d.FbmRId.Model.ToLower().Contains(sText) ||
                 d.FbmRId.Serial.ToLower().Contains(sText)
                 from n in dN.DefaultIfEmpty()
                 select new FeatureMask
                 {
                     Model = d.FbmRId.Model,
                     Serial = d.FbmRId.Serial,
                     Fid = d.FbmFId.Id,
                     Did = d.Id,
                     Name = d.FbmFId.Name,
                     Nominal = d.FbmFId.Nominal,
                     TolPos = d.FbmFId.TolPos,
                     TolNeg = d.FbmFId.TolNeg,
                     Measured = d.Measured,
                     Deviation = d.Deviation,
                     Test = d.Test ? "Pass" : "Fail",
                     NDescription = n == null ? string.Empty : n.NDescription
                 }).ToList<IFeatureMask>();

            return features;
        }
        #endregion

        #region Validate
        //Tien - 13. maj
        public bool StrLen(string str, int length, int minLength = 0)
        {
            if (str.Length > 0)
            {
                return str.Length <= length && str.Length >= minLength;
            }
            return false;
        }
        #endregion
    }
}